home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / TUTOROOT.PAK / STEP08.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  8KB  |  402 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1994 by Borland International
  3. //   Tutorial application -- step08.cpp
  4. //----------------------------------------------------------------------------
  5. #include <owl/pch.h>
  6. #include <owl/applicat.h>
  7. #include <owl/framewin.h>
  8. #include <owl/dc.h>
  9. #include <owl/inputdia.h>
  10. #include <owl/opensave.h>
  11. #include <classlib/arrays.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include "step08.rc"
  15.  
  16. typedef TArray<TPoint> TPoints;
  17. typedef TArrayIterator<TPoint> TPointsIterator;
  18.  
  19. class TLine : public TPoints {
  20.   public:
  21.     TLine(int penSize = 1) : TPoints(10, 0, 10)
  22.     {
  23.       PenSize = penSize;
  24.     }
  25.  
  26.     int QueryPen() const
  27.     {
  28.       return PenSize;
  29.     }
  30.  
  31.     int QueryPen(int penSize);
  32.  
  33.     // The == operator must be defined for the container class, even if unused
  34.     bool operator ==(const TLine& other) const
  35.     {
  36.       return &other == this;
  37.     }
  38.  
  39.     friend ostream& operator <<(ostream& os, const TLine& line);
  40.     friend istream& operator >>(istream& is, TLine& line);
  41.  
  42.   protected:
  43.     int PenSize;
  44. };
  45.  
  46. int
  47. TLine::QueryPen(int penSize)
  48. {
  49.   if (penSize < 0)
  50.     PenSize = 1;
  51.   else if (penSize > 0)
  52.     PenSize = penSize;
  53.   return PenSize;
  54. }
  55.  
  56. typedef TArray<TLine> TLines;
  57. typedef TArrayIterator<TLine> TLinesIterator;
  58.  
  59. class TDrawWindow : public TWindow {
  60.   public:
  61.     TDrawWindow(TWindow* parent = 0);
  62.    ~TDrawWindow()
  63.     {
  64.       delete DragDC;
  65.       delete Pen;
  66.       delete Line;
  67.       delete Lines;
  68.       delete FileData;
  69.     }
  70.  
  71.   protected:
  72.     TDC* DragDC;
  73.     TPen* Pen;
  74.     TLines* Lines;
  75.     TLine* Line; // To hold a single line at a time that later gets
  76.                  // stuck in Lines
  77.     TOpenSaveDialog::TData* FileData;
  78.     bool IsDirty, IsNewFile;
  79.  
  80.     void SetPenSize(int newSize);
  81.     int GetPenSize();
  82.  
  83.     // Override member function of TWindow
  84.     bool CanClose();
  85.  
  86.     // Message response functions
  87.     void EvLButtonDown(uint, TPoint&);
  88.     void EvRButtonDown(uint, TPoint&);
  89.     void EvMouseMove(uint, TPoint&);
  90.     void EvLButtonUp(uint, TPoint&);
  91.     void Paint(TDC&, bool, TRect&);
  92.     void CmFileNew();
  93.     void CmFileOpen();
  94.     void CmFileSave();
  95.     void CmFileSaveAs();
  96.     void CmPenSize();
  97.     void CmAbout();
  98.     void SaveFile();
  99.     void OpenFile();
  100.  
  101.   DECLARE_RESPONSE_TABLE(TDrawWindow);
  102. };
  103.  
  104. DEFINE_RESPONSE_TABLE1(TDrawWindow, TWindow)
  105.   EV_WM_LBUTTONDOWN,
  106.   EV_WM_RBUTTONDOWN,
  107.   EV_WM_MOUSEMOVE,
  108.   EV_WM_LBUTTONUP,
  109.   EV_COMMAND(CM_FILENEW, CmFileNew),
  110.   EV_COMMAND(CM_FILEOPEN, CmFileOpen),
  111.   EV_COMMAND(CM_FILESAVE, CmFileSave),
  112.   EV_COMMAND(CM_FILESAVEAS, CmFileSaveAs),
  113.   EV_COMMAND(CM_ABOUT, CmAbout),
  114.   EV_COMMAND(CM_PENSIZE, CmPenSize),
  115. END_RESPONSE_TABLE;
  116.  
  117. TDrawWindow::TDrawWindow(TWindow* parent)
  118. {
  119.   Init(parent, 0, 0);
  120.   DragDC    = 0;
  121.   Lines     = new TLines(5, 0, 5);
  122.   Line      = new TLine;
  123.   Pen       = new TPen(TColor::Black, Line->QueryPen());
  124.   IsNewFile = true;
  125.   IsDirty   = false;
  126.   FileData  = new TOpenSaveDialog::TData(OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,
  127.                                         "Point Files (*.PT8)|*.pt8|", 0, "",
  128.                                         "PT8");
  129. }
  130.  
  131. bool
  132. TDrawWindow::CanClose()
  133. {
  134.   if (IsDirty)
  135.     switch(MessageBox("Do you want to save?", "Drawing has changed",
  136.                       MB_YESNOCANCEL | MB_ICONQUESTION)) {
  137.       case IDCANCEL:
  138.         // Choosing Cancel means to abort the close -- return false.
  139.         return false;
  140.  
  141.       case IDYES:
  142.         // Choosing Yes means to save the drawing.
  143.         CmFileSave();
  144.     }
  145.   return true;
  146. }
  147.  
  148. void
  149. TDrawWindow::EvLButtonDown(uint, TPoint& point)
  150. {
  151.   if (!DragDC) {
  152.     SetCapture();
  153.     DragDC = new TClientDC(*this);
  154.     DragDC->SelectObject(*Pen);
  155.     DragDC->MoveTo(point);
  156.     Line->Add(point);
  157.     IsDirty = true;
  158.   }
  159. }
  160.  
  161. void
  162. TDrawWindow::EvRButtonDown(uint, TPoint&)
  163. {
  164.   SetPenSize(GetPenSize());
  165. }
  166.  
  167. void
  168. TDrawWindow::EvMouseMove(uint, TPoint& point)
  169. {
  170.   if (DragDC) {
  171.     DragDC->LineTo(point);
  172.     Line->Add(point);
  173.   }
  174. }
  175.  
  176. void
  177. TDrawWindow::EvLButtonUp(uint, TPoint&)
  178. {
  179.   if (DragDC) {
  180.     ReleaseCapture();
  181.     Lines->Add(*Line);
  182.     Line->Flush();
  183.     delete DragDC;
  184.     DragDC = 0;
  185.   }
  186. }
  187.  
  188. void
  189. TDrawWindow::CmPenSize()
  190. {
  191.   SetPenSize(GetPenSize());
  192. }
  193.  
  194. int
  195. TDrawWindow::GetPenSize()
  196. {
  197.   char inputText[6];
  198.   int newPenSize = 1;
  199.  
  200.   wsprintf(inputText, "%d", Line->QueryPen());
  201.   if ((TInputDialog(this, "Line Thickness",
  202.                         "Input a new thickness:",
  203.                         inputText,
  204.                         sizeof(inputText))).Execute() == IDOK) {
  205.     newPenSize = atoi(inputText);
  206.  
  207.     if (newPenSize < 0)
  208.       newPenSize = 1;
  209.   }
  210.   return newPenSize;
  211. }
  212.  
  213. void
  214. TDrawWindow::SetPenSize(int newSize)
  215. {
  216.   delete Pen;
  217.   Pen = new TPen(TColor::Black, Line->QueryPen(newSize));
  218. }
  219.  
  220. void
  221. TDrawWindow::Paint(TDC& dc, bool, TRect&)
  222. {
  223.   // Iterates through the array of line objects.
  224.   TLinesIterator i(*Lines);
  225.  
  226.   while (i) {
  227.     // Set pen for the dc to current line's pen.
  228.     TPen pen(TColor::Black, i.Current().QueryPen());
  229.     dc.SelectObject(pen);
  230.  
  231.     // Iterates through the points in the line i.
  232.     TPointsIterator j(i++);
  233.     bool first = true;
  234.  
  235.     while (j) {
  236.       TPoint p = j++;
  237.  
  238.       if (!first)
  239.         dc.LineTo(p);
  240.       else {
  241.         dc.MoveTo(p);
  242.         first = false;
  243.       }
  244.     }
  245.     dc.RestorePen();
  246.   }
  247. }
  248.  
  249. void
  250. TDrawWindow::CmFileNew()
  251. {
  252.   if (CanClose()) {
  253.     Line->Flush();
  254.     Lines->Flush();
  255.     Invalidate();
  256.     IsDirty = false;
  257.     IsNewFile = true;
  258.   }
  259. }
  260.  
  261. void
  262. TDrawWindow::CmFileOpen()
  263. {
  264.   if (CanClose())
  265.     if ((TFileOpenDialog(this, *FileData)).Execute() == IDOK)
  266.       OpenFile();
  267. }
  268.  
  269. void
  270. TDrawWindow::CmFileSave()
  271. {
  272.   if (IsNewFile)
  273.     CmFileSaveAs();
  274.   else
  275.     SaveFile();
  276. }
  277.  
  278. void
  279. TDrawWindow::CmFileSaveAs()
  280. {
  281.   if (IsNewFile)
  282.     strcpy(FileData->FileName, "");
  283.  
  284.   if ((TFileSaveDialog(this, *FileData)).Execute() == IDOK)
  285.     SaveFile();
  286. }
  287.  
  288. void
  289. TDrawWindow::CmAbout()
  290. {
  291.   TDialog(this, IDD_ABOUT).Execute();
  292. }
  293.  
  294. void
  295. TDrawWindow::SaveFile()
  296. {
  297.   ofstream os(FileData->FileName);
  298.  
  299.   if (!os)
  300.     MessageBox("Unable to open file", "File Error", MB_OK | MB_ICONEXCLAMATION);
  301.   else {
  302.     // Write the number of lines in the figure
  303.     os << Lines->GetItemsInContainer() << '\n';
  304.  
  305.     // Get an iterator for the array of lines
  306.     TLinesIterator i(*Lines);
  307.  
  308.     // While the iterator is valid (i.e. we haven't run out of lines)
  309.     while (i) {
  310.       // Copy the current line from the iterator and increment the array.
  311.       TLine line = i++;
  312.       os << line;
  313.     }
  314.  
  315.     // Set new file and dirty display indicator to false.
  316.     IsNewFile = IsDirty = false;
  317.   }
  318. }
  319.  
  320. void
  321. TDrawWindow::OpenFile()
  322. {
  323.   ifstream is(FileData->FileName);
  324.  
  325.   if (!is)
  326.     MessageBox("Unable to open file", "File Error", MB_OK | MB_ICONEXCLAMATION);
  327.   else {
  328.     unsigned numLines;
  329.  
  330.     Lines->Flush();
  331.     Line->Flush();
  332.  
  333.     is >> numLines;
  334.  
  335.     while (numLines--) {
  336.       TLine line;
  337.       is >> line;
  338.       Lines->Add(line);
  339.     }
  340.   }
  341.   IsNewFile = IsDirty = false;
  342.   Invalidate();
  343. }
  344.  
  345. class TDrawApp : public TApplication {
  346.   public:
  347.     TDrawApp() : TApplication() {}
  348.  
  349.     void InitMainWindow()
  350.     {
  351.       SetMainWindow(new TFrameWindow(0, "Drawing Pad", new TDrawWindow));
  352.       GetMainWindow()->AssignMenu("COMMANDS");
  353.     }
  354. };
  355.  
  356. int
  357. OwlMain(int /*argc*/, char* /*argv*/ [])
  358. {
  359.   return TDrawApp().Run();
  360. }
  361.  
  362. ostream&
  363. operator <<(ostream& os, const TLine& line)
  364. {
  365.   // Write the number of points in the line
  366.   os << line.GetItemsInContainer();
  367.  
  368.   // Write the pen size
  369.   os << ' ' << line.PenSize;
  370.  
  371.   // Get an iterator for the array of points
  372.   TPointsIterator j(line);
  373.  
  374.   // While the iterator is valid (i.e. we haven't run out of points)
  375.   while(j)
  376.     // Write the point from the iterator and increment the array.
  377.     os << j++;
  378.  
  379.   os << '\n';
  380.   // return the stream object
  381.   return os;
  382. }
  383.  
  384. istream&
  385. operator >>(istream& is, TLine& line)
  386. {
  387.   unsigned numPoints;
  388.  
  389.   is >> numPoints;
  390.  
  391.   is >> line.PenSize;
  392.  
  393.   while (numPoints--) {
  394.     TPoint point;
  395.     is >> point;
  396.     line.Add(point);
  397.   }
  398.   // return the stream object
  399.   return is;
  400. }
  401.  
  402.